import Vue from 'vue'

import 'normalize.css/normalize.css' // A modern alternative to CSS resets

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
// import locale from 'element-ui/lib/locale/lang/en' // lang i18n

import '@/styles/index.scss' // global css

import App from './App'
import store from './store'
import router from './router'

import '@/icons' // icon
import '@/permission' // permission control
import ComponentObj from '@/components'
// 全局注册
Vue.use(ComponentObj)

// set ElementUI lang to EN
// Vue.use(ElementUI, { locale })
// 如果想要中文版 element-ui，按如下方式声明
Vue.use(ElementUI)

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
})
// 项目思路
// 从0开始: 你要选项目模板(vue官方脚手架-自己一点点搭)/用vue-admin-template(你要做的项目也必须是类似的oa办公自动化项目)/百度找找
// 从0.5开始: 读代码, 在它的基础上进行开发(用现有的工具)
// 从1修改: 写完的项目, 也得读代码, 针对性定点修改

// 读代码
// 你全都负责: 所有代码尽力读懂
// 你负责某个模块(页面)-多人开发: "全局"的东西和你的页面vue文件, 别人的不用管
// 总结: 但是如果时间紧任务重, 一定先读封装的那些工具/组件, 然后先看你要修改的相关页面(别的先放放)

// 旭哥的经验:
// 1. 写需求(代码)的套路 先静后动
// (1): 明确需求, 明确目标 (你要知道做完的效果是什么?想要什么?)
// 例如: 我要做登录, 最终效果, 输入账号密码, 点击登录, 提示登录成功
// (2): html+css -> 要的页面先准备一下 (不要管js和功能) -铺页面
// (3): 铺数据/改数据/校验/收集数据(v-model) -> 微调页面文字, 有数据要请求铺设到页面上
// (4): js入场编写交互功能 (小步一个个小功能实现) -> 逻辑(前端先做好)
// (5): 如果需要调用接口, 在和后端配合, 调用ajax->请求

// UI组件/其他插件使用套路
// (1): 明确需求, 目标, 要知道自己想要什么效果的(组件库里找/github找/百度找/以前项目里找)
// (2): 找组件: 类似组件->看看有没有官网(有最好), 没有看npmjs.com/github.com上readme说明书
// (3): 下载+引入组件: 把组件弄到自己项目里, npm下载
// (4): 用组件: 把基础代码复制过来
// (5): 读组件: 把每个标签, 嵌套关系, 属性, 事件, 都写好注释弄明白->多看文档
// (6): 改组件(改配置/属性/删除多余的)

// 写html+css套路
// 从大到小, 从上到下, 每个小块里, 从左到右, 分div, 然后填充标签, 调整css

// 2. 封装函数, 什么时候需要参数, 什么时候需要返回return
// (1): 函数内, 某个值自己内部不能确定/每次函数调用都不一样, 必须留好形参让外传入
// (2): 函数调用处(外面), 需要函数内处理后的"结果", 必须return出去

// 3. 什么是跨域
// (1): 跨域是"浏览器"对"ajax"做出的同源策略限制
// (2): 同源指的是, 网页在浏览器打开时, 地址栏里的地址中协议, 域名, 端口
// 和内嵌的ajax请求的url地址中协议, 域名, 端口有一个对不上就跨域了
// 注意: 服务器和服务器之间的请求是没有跨域限制的

// 4. 如何解决跨域问题?
// 方式1: jsonp
// 注意: jsonp和json没有关系, JSON是一种序列化数据的技术, JSONP是解决跨域的技术
// 使用: script标签的src属性, 来发送请求而且它不受跨域限制, 请求后让后台返回一个函数调用字符串+数据, 在前端进入到script标签之间, 当做js代码执行, 把数据带回来
// 特点: 需要前端传递一个方法名, 后端返回函数调用格式的字符串
// 要求: 前端和后端同时支持

// 方式2: cors
// 概念: 跨域资源共享, 现代浏览器前端默认支持的, 但是还需要后端开启才行
// 使用: cors是让后端进行设置
// 特点: 你可以在响应头里看看有没有一个叫"Access-Control-Allow-Origin"字段(是后台设置的, 作用: 允许哪些源进行跨域访问)
// 要求: 前端什么都不用做, 正常使用axios发送ajax请求, 只需要后端开启(前端无需感知)

// 方式3: 代理服务器
// 针对: 后端不开跨域支持, 我们前端自己用代理服务器也能拿到数据
// 原理: 前端代理服务器, 请求后端接口服务器, 因为服务器之间没有跨域限制
// 好在: vue脚手架有一个webpack开发服务器支持, 给这个服务器进行配置, 让他支持代理转发
// 1. 让axios请求, 不要直接请求外链地址(http开头的), 而是要请求/开头, 代表当前所在服务器(http://localhost:9528)
// 2. 配置代理转发的规则, vue.config.js中devServer的proxy选项内配置(让开发服务器支持代理转发)
// 前提: 后端真的有"接口地址"可以使用, 才能用ajax请求 (前后端分离的项目)

// 特殊: 后端渲染的项目(SSR/nuxt.js技术->新学vue语法), 数据在后端渲染完毕返回给前端网页不用你使用ajax请求

// 5. 后台返回数据的类型
// 类型1: 失败的请求, 后台会返回400的http状态码(错误)
// "http状态码"来标记失败情况

// 类型2: 无论成功/失败的请求, 后台都会返回http状态200(ok)
// 但是在"数据的字段"上区别成功/失败

// 6. 旭哥经验
// 听懂了, 掌握20%
// 抄出来, 掌握30%
// 根据自己思路, 写出来 50%
// 能给自己, 讲讲, 掌握60%
// 能给别人讲明白 80%
// 能写出文字, 给别人讲明白/设计例子, 100%

// 7. .native使用
// 前提: 组件身上绑定"原生名字"事件, 但是组件身上虽然名字是原生的, 但是都需要组件内$emit触发才支持
// 如果组件内不支持这个原生名字的事件
// 知道: 查看文档/试试, 有的组件是支持一些原生的事件名, 就可以直接绑定使用
// 解决: 我们就可以给组件的@原生名字事件.native -> 告诉vue给它绑定成原生的事件, 而不是自定义事件
// 例如: <el-xxxx @click.native></el-xxxx>

// 8.回调地狱
// 异步请求, ajax/axios都有回调函数onload/then()里函数体 在回调函数里拿到结果
// 拿到结果以后, 在这个函数体里, 再次发起请求, 又会有一个函数体嵌入在这里, 继续嵌套请求+回调函数...嵌套下去
// 形成了回调地狱

// 9. vue组件样式相关
// (1): 运行时,选中标签, 看右侧的style里样式被划线划掉了, 优先级不够(权限)
// (2): /deep/ 选中组件内的选择器, 如果看右侧的style样式类名已经上去了证明已经选中了跟/deep/没啥关系, 如果发现类名写了, 但是没上去, 运行时选择器没有选到组件内类名(/deep/)
// /deep/作用: 把scope加的属性选择器加到类名的前面, 选中组件内无属性的类名
// (3): 用错了, svg要用fill属性填充图标颜色, 而不能用style影响颜色

// 10. 能不能干活?
// 三个方面
// (1): 听到需求描述, 脑子里有没有项目运行的"画面"? 知不知道要什么效果? -> 多用网站/电脑
// (2): 细化细分步骤123..步(越小越好, 写注释), 把思路转成代码 -> 多写注释+多仿写代码
// (3): 多总结问题, 记录到小本上(仿照旭哥记录错误的方式)http://lidongxuwork.gitee.io/error/ -> 遇到问题/打印调试/....百度解决

// 11. 封装
// 好处: 方便以后替换, 方便复用, 固定的值放在统一位置管理
// 例如: 为何你的基地址要封装?
// 最好: 逻辑页面不出现固定的文字/数字->封装到一个统一的js文件使用
// 有自然语言的意思的值(可能会频繁变化的)

// 12. 如何找到标签与之对应的代码?
// (1). 用类名/关键文字, 回来放大镜搜索(如果有多个地方, 一定要关联起来读读)
// (2). 如果第一种翻遍了没有, 那可能是后台返回的动态数据看network相关接口
// (3). 既不是前端写固定, 也不是后台返回的文字, 组件库内置的(包内置)
// (4). 它有可能是图片...

// 13. v-model是Vue的指令(语法糖)
// <标签 v-model="vue变量"></标签>
// 作用: 实现数据双向绑定
// 双向: 当前标签的value属性和vue变量双向绑定到一起
// v-model运行时, 会给当前标签添加 :value="vue变量", 还会给当前标签绑定@input事件, 把事件的值赋予给vue变量
// 本质: <标签 :value="vue变量" @input="(值) => vue变量 = 值">
// 问题: 我除了在表单标签上用v-model, 自定义的组件身上是否可以使用v-model?
// 可以...但是需要组件内定义props: 必须叫value, 内部检测输入框改变, 必须触发$emit('input', 值)
// 例子: 微信群里

// 14. 刷新token的思路
// (1): 现在用, axios响应拦截器里, 判断401, 强制清除本地和vuex的token值, 强制回到登录页面(用户有感知/让用户重新登录, 拿到新的token)
// (2): 无感知, axios响应拦截器里, 判断401, 强制清除过期的vuex和本地的token值
// 前提: 后端提供了刷新token的接口, 登录时, 会给你返回2个token(一个是普通用的token,另一个叫refresh_token值), 调用刷新token的接口, 把refresh_token传递给后台, 换回一个新的token, 而不必强制跳转登录页面, 让用户重新登录
// 例如: 微信

// 15. Vue的生命周期
// 概念: Vue实例(new Vue或者每个组件对象)从创建到销毁的过程
// 钩子函数: (生命周期函数), 组件对象在每个阶段会自动执行一些固定名字的函数(通知我们到达了那个阶段)
// 记住: 每个钩子函数的特点即可
// 阶段: 4大阶段
// 方法: 8个方法
// (1): 初始化(创建)阶段 beforeCreate created
// (2): 挂载阶段 beforeMount mounted
// (3): 更新阶段 beforeUpdate updated
// (4): 销毁阶段 beforeDestroy destroyed

// 特点:
// beforeCreate (this实例上还没有添加data/methods属性)
// created (this实例上能访问到data和methods里定义的属性和方法) - 早发早享受数据而且可以拿到data里的变量赋值
// beforeMount (虚拟DOM还没有变成真实的DOM, 不要在这里获取真实DOM, 拿不到的)
// mounted (想获取真实DOM标签, 一般在这里获取)
// 当你的data里/计算属性/this实例里的变量发生变化的时候, 执行更新的钩子函数
// beforeUpdate (数据变化了, 但是真实DOM还没有更新)
// updated (数据变化了, 真实DOM更新完毕, 会触发此函数)
// 当组件用v-if/调用组件$destroy()方法, 当前组件会被从内存里销毁掉
// 前者DOM也一起没了, 后者标签还在组件对象没了
// beforeDestroy
// destroyed - 应用: 去掉当前组件占用的全局资源(window.adDEventListeners就要在这个阶段销毁事件监听, 计时器/定时器)

// 补充: 3个方法
// 前提: 你使用keep-alive缓存的组件, 会新增2个钩子函数
// activated - 触发激活 (切换回来) -> 类似created
// deActivated - 失去激活 (被切走了) -> 类似destroyed
// 注意: 组件被缓存, created只走第一次, 以后不在执行(所以用activated来代替created, 检测组件回来了), destroyed不会触发组件缓存不销毁, 用deActivated来替代, 监视此组件被切走了

// errorCapture:偶尔用, 捕获子组件里的报错

// 16. vue组件的运用
// 其实组件都是.vue文件, 没有区别, 旭哥划分的区别是为了方便大家写代码
// 组件分为2类
// (1): 页面组件: 都是和路由配合使用 / 作为页面的某一部分 (业务逻辑/数据处理/网络请求调用)
// (2): 复用组件: 当前页面多次使用/别的页面也要使用它 (只负责展示数据, 所有的逻辑和网络请求都传回到页面组件里编写) -> 如果有父子关系还有遵守单向数据流

// 17. 请求参数如何看?
// 后台要求?查询字符串(英文叫query), axios就在params里发, 的对象参数名和值就会被axios处理后拼接在?后面请求后台接口
// 后台要求请求体(英文叫body), axios就在data里发, 装载请求体里给后台
// 后台要求请求头(英文叫Header), axios里headers选项里发, 装载在请求头上
